package com.net.okhttphelper.http;

import android.text.TextUtils;

import com.net.okhttphelper.constant.RequestMethod;
import com.net.okhttphelper.download.DownloadListener;
import com.net.okhttphelper.upload.UploadListener;
import com.net.okhttphelper.utils.FileNameUtil;
import com.net.okhttphelper.utils.HttpUrlUtils;

import java.io.File;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

import okhttp3.Headers;
import okhttp3.MediaType;
import okhttp3.MultipartBody;
import okhttp3.Request;
import okhttp3.RequestBody;

/**
 * 构建请求Request
 * @author jie
 */
public class HttpRequest {

    /**
     * json请求参数格式
     */
    private final static String REQUEST_BODY_JSON = "application/json; charset=utf-8";
    /**
     * 表单请求参数格式
     */
    private final static String REQUEST_BODY_FORM_DATA = "multipart/form-data";

    /**
     * 构建一个请求
     */
    public static Request createRequest(RequestParams params, String baseUrl, UploadListener uploadListener, DownloadListener downloadListener) {
        String url = params.getUrl();
        String tag = params.getTag();
        ConcurrentHashMap<String, String> queryParams = params.getQueryParams();
        ConcurrentHashMap<String, String> headerParams = params.getHeaderParams();
        String method = params.getMethod();
        // 拼接baseUrl
        url = HttpUrlUtils.verifyUrl(url, baseUrl);
        // 拼接请求路径
        url = joinUrl(url, queryParams);
        // 构建请求头
        Headers mHeader = getHeader(headerParams);
        Request.Builder builder = new Request.Builder()
                .url(url).headers(mHeader).tag(tag);
        boolean isPost = method.equals(RequestMethod.POST);
        boolean isPut = method.equals(RequestMethod.PUT);
        if (isPost || isPut){
            RequestBody param;
            ConcurrentHashMap<String, String> fileParams = params.getFileParams();
            if (isPost && !fileParams.isEmpty()){
                // 触发文件上传请求,注意requestBody字段将丢失
                param = getFileRequestBody(fileParams);
            }else{
                String requestBody = params.getRequestBody();
                // RequestBody不能为空，故使用空字符
                String requestBodyStr = TextUtils.isEmpty(requestBody) ? "" : requestBody;
                // 构建请求请求体
                param = RequestBody.create(MediaType.parse(REQUEST_BODY_JSON), requestBodyStr);
            }
            builder.method(method, param);
        }else{
            builder.method(method, null);
        }
        // 添加文件上传和下载监听tag
        addProgressListener(builder, uploadListener, downloadListener);
        return builder.build();
    }

    /**
     * 拼接请求路径
     */
    private static String joinUrl(String url, ConcurrentHashMap<String, String> queryParams) {
        StringBuilder urlBuilder = new StringBuilder(url);
        if (queryParams != null && (!queryParams.isEmpty())) {
            urlBuilder.append("?");
            for (Map.Entry<String, String> entry : queryParams.entrySet()) {
                String key = entry.getKey();
                String value = entry.getValue();
                urlBuilder.append(key).append("=").append(value).append("&");
            }
            // 移除最后的 & 符号
            url = urlBuilder.substring(0, urlBuilder.length() - 1);
        }
        return url;
    }

    /**
     * 构建请求头
     */
    private static Headers getHeader(ConcurrentHashMap<String, String> headerParams) {
        //添加请求头
        Headers.Builder mHeaderBuild = new Headers.Builder();
        if (headerParams != null && (!headerParams.isEmpty())) {
            for (Map.Entry<String, String> entry : headerParams.entrySet()) {
                mHeaderBuild.add(entry.getKey(), entry.getValue());
            }
        }
        return mHeaderBuild.build();
    }

    /**
     * 构建文件上传的请求体
     */
    private static RequestBody getFileRequestBody(ConcurrentHashMap<String, String> fileParams){
        MultipartBody.Builder builder = new MultipartBody.Builder()
                .setType(MultipartBody.FORM);
        for (Map.Entry<String, String> entry : fileParams.entrySet()) {
            String key = entry.getKey();
            String filePath = entry.getValue();
            builder.addFormDataPart(key, FileNameUtil.getFileNameByPath(filePath),
                    RequestBody.create(MediaType.parse(REQUEST_BODY_FORM_DATA), new File(filePath)));
        }
        return builder.build();
    }

    /**
     * 添加上传和下载进度监听
     */
    private static void addProgressListener(Request.Builder builder, UploadListener uploadListener,
                                            DownloadListener downloadListener) {
        if (uploadListener != null){
            builder.tag(UploadListener.class, uploadListener);
        }
        if (downloadListener != null){
            builder.tag(DownloadListener.class, downloadListener);
        }
    }

}
